﻿using System;
using System.Collections.Generic;
using UnityEngine;

namespace UniFramework.RedPoint
{
    public class RedPointTreeNode
    {
        private ERedPointType ownRedPointType;

        /// <summary>
        /// 红点类型
        /// </summary>
        public ERedPointType RedPointType => ownRedPointType;

        /// <summary>
        /// 当前节点是否激活
        /// </summary>
        private bool _isActive;

        /// <summary>
        /// 是否需要显示红点
        /// </summary>
        public bool IsActive => _isActive;

        /// <summary>
        /// 父节点
        /// </summary>
        public RedPointTreeNode FatherNode;

        /// <summary>
        /// 子节点集合
        /// </summary>
        private Dictionary<ERedPointType, RedPointTreeNode> _childrenRedPointDic;

        /// <summary>
        /// 子节点激活数量
        /// </summary>
        private int _childrenRedPointActiveCnt;


        /// <summary>
        /// 子节点激活的数量
        /// </summary>
        public int ChildrenRedPointActiveCnt => _childrenRedPointActiveCnt;

        /// <summary>
        /// 子节点失活的数量
        /// </summary>
        public int ChildrenRedPointNotActiveCnt
        {
            get
            {
                if (_childrenRedPointDic == null) return 0;
                return _childrenRedPointDic.Count - _childrenRedPointActiveCnt;
            }
        }

        /// <summary>
        /// 子节点总数
        /// </summary>
        public int ChildCnt => _childrenRedPointDic?.Count ?? 0;

        /// <summary>
        /// 当数据更新时做的事情
        /// </summary>
        public event Action<RedPointTreeNode, bool> OnNodeActiveValueChange;

        /// <summary>
        /// 当子节点数据发生改变时做的事情
        /// </summary>
        public event Action<RedPointTreeNode, bool> OnSonNodeValueChange;


        public virtual void Init(ERedPointType ownERedPointType, RedPointTreeNode fatherNode)
        {
            _isActive = false;
            FatherNode = fatherNode;
            this.ownRedPointType = ownERedPointType;
            _childrenRedPointDic = new Dictionary<ERedPointType, RedPointTreeNode>();
            _childrenRedPointActiveCnt = 0;
            this.OnSonNodeValueChange += OnSonNodeValueChangeHandler;
        }

        public void Dispose()
        {
            this.OnSonNodeValueChange -= OnSonNodeValueChangeHandler;
            _childrenRedPointDic.Clear();
            _childrenRedPointActiveCnt = 0;
            _childrenRedPointDic = null;
        }

        /// <summary>
        /// 当节点数据发生改变时
        /// 1.触发当前自己的数据改变事件
        /// 2.触发父节点的数据改变事件
        /// </summary>
        /// <param name="isActive"></param>
        public virtual void ChangeNodeState(bool isActive)
        {
            if (isActive == this._isActive)
                return;
            Debug.Log($"{ownRedPointType.ToString()} ChangeNodeState:{isActive}");
            this._isActive = isActive;
            OnNodeActiveValueChange?.Invoke(this, isActive);
            FatherNode?.OnSonNodeValueChange?.Invoke(this, isActive);
        }

        /// <summary>
        /// 添加子节点
        /// </summary>
        /// <param name="sonNode"></param>
        /// <exception cref="Exception"></exception>
        public virtual void AddSonNode(RedPointTreeNode sonNode)
        {
            if (!_childrenRedPointDic.ContainsKey(sonNode.RedPointType))
            {
                _childrenRedPointDic.Add(sonNode.RedPointType, sonNode);
                if (sonNode.IsActive)
                    ++_childrenRedPointActiveCnt;
            }
            else
            {
                throw new Exception($"{sonNode.RedPointType} is already exist");
            }
        }

        /// <summary>
        /// 当子节点数据发生改变时，父节点需要去尝试修正当前自己的值以及自己父节点的值
        /// </summary>
        /// <param name="redPointTreeNode"></param>
        /// <param name="isActive"></param>
        private void OnSonNodeValueChangeHandler(RedPointTreeNode redPointTreeNode, bool isActive)
        {
            _childrenRedPointActiveCnt += redPointTreeNode.IsActive ? 1 : -1;
            _childrenRedPointActiveCnt = Math.Max(0, _childrenRedPointActiveCnt);
            ChangeNodeState(_childrenRedPointActiveCnt != 0);
        }
    }
}